package com.hup.utils.commons.hardware;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;

import javax.swing.*;
import java.awt.*;

/**
 * 多屏幕情况的工具类
 *
 * @author hugan
 * @date 2020/5/23
 */
@Log4j2
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ScreenUtilExtend {

    /**
     * 判断目标是否在屏幕内(与任意一个屏幕有交集)
     */
    public static boolean isInsideScreens(Rectangle rect) {
        GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
        GraphicsDevice res = null;
        int maxSpace = 0;

        for (GraphicsDevice device : devices) {
            Rectangle bounds = device.getDefaultConfiguration().getBounds();
            int space = getSpace(bounds, rect);
            if (space > maxSpace) {
                //等于时,取靠前的设备
                maxSpace = space;
                res = device;
            }
        }
        return res != null;
    }

    /**
     * 目标坐标所在的屏幕device
     *
     * @param point {@link Component#getLocation()},被检测的坐标
     * @param useDefault 不在任意屏幕内时,返回默认屏幕
     * @return null-不在任意屏幕内
     */
    public static GraphicsDevice getDevice(Point point, boolean useDefault) {
        GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
        for (GraphicsDevice device : devices) {
            Rectangle bounds = device.getDefaultConfiguration().getBounds();
            log.debug("bounds={}", bounds);
            boolean insideX = point.x >= bounds.x && point.x < bounds.x + bounds.width;
            boolean insideY = point.y >= bounds.y && point.y < bounds.y + bounds.height;
            if (insideX && insideY) {
                log.debug("inside={}", bounds);
                return device;
            }
        }
        return !useDefault ? null : GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
    }

    /**
     * 获取目标窗口[{@link JFrame},{@link JWindow},{@link JDialog}]所在的屏幕设备;
     * <pre>
     * .单屏幕时,返回默认设备
     * .多屏幕时,返回窗口占用面积最大的那个设备
     * </pre>
     *
     * @return nullable, 多屏幕时, 在所有屏幕外
     */
    public static GraphicsDevice getDevice(Window w) {
        GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
        if (devices.length == 1) return devices[0];

        Point point = w.getLocationOnScreen();
        Rectangle rectWindow = new Rectangle(point.x, point.y, w.getWidth(), w.getHeight());

        GraphicsDevice res = devices[0];
        int maxSpace = 0;

        for (GraphicsDevice device : devices) {
            Rectangle bounds = device.getDefaultConfiguration().getBounds();
            log.debug("dev={}, bounds={}", device.getIDstring(), bounds);

            int space = getSpace(bounds, rectWindow);
            if (space > maxSpace) {
                //等于时,取靠前的设备
                maxSpace = space;
                res = device;
            }
        }
        log.debug("res={}", res.getIDstring());
        return res;
    }

    /**
     * 计算两个矩形的交集面积
     *
     * @apiNote https://blog.csdn.net/woaicide/article/details/51658322
     */
    private static int getSpace(Rectangle r1, Rectangle r2) {
        Point p1 = new Point(Math.max(r1.x, r2.x), Math.max(r1.y, r2.y));
        Point p2 = new Point(Math.min(r1.x + r1.width, r2.x + r2.width),
                Math.min(r1.y + r1.height, r2.y + r2.height));
        if (p2.x > p1.x && p2.y > p1.y) {
            int wid = p2.x - p1.x;
            int hei = p2.y - p1.y;
            int space = wid * hei;
            log.debug("p1,p2=[{}, {}]space={}x{}={}", p1, p2, wid, hei, space);
            return space;
        }
        return 0;
    }

}
